
struct Light
{
  vec4 position;
  vec4 ambient;
  vec4 diffuse;
  vec4 specular;
  vec3 attenuation;
};

struct Material
{
  vec4  ambient;
  vec4  diffuse;
  vec4  specular;
  float shininess;
  vec4  emission;
};




vec4 calculate_phong_lighting (
                                mat4      mat_world,
                                mat4      mat_view,
                                vec4      lVertex,
                                vec3      lNormal,
                                Light     light,
                                Material  mat
                                )
{
  // the resulting color
  vec4 color = vec4 (0.0, 0.0, 0.0, 0.0);



  //
  // setup the light specific values

  // normalized vector pointing from vertex to light in world space
  vec3 wVertToLight;
  // with point lights we have an attenuation factor.
  float attenuated_value = 1.0;

  vec3 wPos = (mat_world * lVertex).xyz;
  if (light.position.w < 0.5)
  {
    // directional light
    wVertToLight = normalize (-light.position.xyz);
  }
  else
  {
    wVertToLight = light.position.xyz - wPos;
    
    float dist = length (wVertToLight);
    float dist_q = dist * dist;
    wVertToLight = normalize (wVertToLight);

    attenuated_value =  light.attenuation.x + 
                        light.attenuation.y * dist + 
                        light.attenuation.z * dist_q;
    attenuated_value = clamp (attenuated_value, 0.0, 1.0);
  }


  vec3 wNormal = (mat_world * vec4 (lNormal.xyz, 0.0)).xyz;

  color = mat.ambient * light.ambient;

  float dt = dot (wNormal, wVertToLight);
  if (dt > 0.0)
  {
    color += dt * mat.diffuse * light.diffuse;
  }


  //
  // calculated the optimal vector of reflected light in view coordinates
  vec3 wVertToLightRefl = reflect (wVertToLight, wNormal);
  vec3 vVertToLightRefl = (mat_view * vec4 (wVertToLightRefl, 0.0)).xyz;
  vec3 vVertToEye = normalize ((mat_view * vec4 (wPos, 1.0)).xyz);

  float st = pow (dot (vVertToEye, vVertToLightRefl), mat.shininess);
  if (st > 0.0)
  {
    color += st * mat.specular * light.specular;
  }
  
  color += mat.emission;
  
  
  color *= attenuated_value;

  return color;
}



